/*
 * SOLMIX PROJECT
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */

package org.solmix.fmk.event;

import org.osgi.framework.BundleContext;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.solmix.SLXConstants;
import org.solmix.api.event.IValidationEvent.Level;
import org.solmix.api.event.IValidationEvent.OutType;
import org.solmix.api.event.MonitorEventFactory;
import org.solmix.api.event.ValidationEventWrapper;
import org.solmix.api.exception.SLXException;
import org.solmix.commons.logs.Logger;
import org.solmix.fmk.datasource.ValidationEventFactory;

/**
 * <code>EventManager</code> used to hold Osgi Event Admin Service.
 * 
 * @author solmix
 * @version 0.0.4
 * @since 0.0.4
 */

public class EventManager
{

    public static volatile EventAdmin eventAdmin;

    private static volatile BundleContext context;

    public synchronized void unregister_eventAdmin(EventAdmin eventAdmin) {
        EventManager.eventAdmin = null;
    }

    public synchronized void register_eventAdmin(EventAdmin eventAdmin) {
        EventManager.eventAdmin = eventAdmin;
    }

    /**
     * @return the context
     */
    public static BundleContext getContext() {
        return context;
    }

    /**
     * @param context the context to set
     */
    public void setContext(BundleContext context) {
        EventManager.context = context;
    }

    /**
     * Initiate asynchronous delivery of an event. This method returns to the caller before delivery of the event is
     * completed.
     * 
     * @param event The event to send to all listeners which subscribe to the topic of the event.
     * 
     * @throws SecurityException If the caller does not have <code>TopicPermission[topic,PUBLISH]</code> for the topic
     *         specified in the event.
     */
    public static void postEvent(Event event) {
        if (eventAdmin != null)
        eventAdmin.postEvent(event);
        else
            notSet();
    }

    public static boolean haveAdmin() {
        return eventAdmin != null;
    }
    /**
     * Initiate synchronous delivery of an event. This method does not return to the caller until delivery of the event
     * is completed.
     * 
     * @param event The event to send to all listeners which subscribe to the topic of the event.
     * 
     * @throws SecurityException If the caller does not have <code>TopicPermission[topic,PUBLISH]</code> for the topic
     *         specified in the event.
     */
    public static void sendEvent(Event event) {

        if (eventAdmin != null)
        eventAdmin.sendEvent(event);
        else
            notSet();
    }

    private static void notSet() {
        if (SLXConstants.isOSGI())
            throw new NullPointerException("EventAdmin Service not reserved!");
        else
            return;
    }

    public static void createAndFireTimeMonitorEvent(long time, String msg) {
        MonitorEventFactory factory;
        if (getContext() == null)
            factory = MonitorEventFactory.getDefault();
        else
            factory = MonitorEventFactory.getInstance(getContext());
        Event e = factory.createTimeMonitorEvent(time, msg);
        if (haveAdmin())
            postEvent(e);
        else
            Logger.timing.debug(msg + "[" + time + "ms]");
    }

    public static void createAndFireDSValidationEvent(Level level, String msg, Throwable e) {
        ValidationEventFactory factory = ValidationEventFactory.instance();
        factory.setType(ValidationEventFactory.TYPE_DS);
        try {
            Event event = ValidationEventWrapper.wrapper(factory.create(OutType.SERVER, level, "", msg, e));

            if (haveAdmin())
                postEvent(event);
            else
                Logger.timing.debug(msg);
        } catch (SLXException e1) {

            Logger.timing.error("create event failed", e1);
        }
    }

    public static void createAndFireDSValidationEvent(Level level, String msg) {
        createAndFireDSValidationEvent(level, msg, null);
    }
}
